﻿ 
 
using System.Collections.Generic;

// ReSharper disable CheckNamespace
namespace System.Web.UI
// ReSharper restore CheckNamespace
{
	/// <summary>
    ///  Extensions for HtmlTextWriter
    /// </summary>
	public static partial class HtmlWriterTextTagExtensions
	{
		static readonly Stack<Tag> tags = new Stack<Tag>();

		#region Html tag writer methods
			
			/// <summary>
			///  Opens a Unknown Html tag
			/// </summary>
			public static HtmlTextWriter Unknown(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("Unknown", atts); 
			}
			
			/// <summary>
			///  Opens a A Html tag
			/// </summary>
			public static HtmlTextWriter A(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("a", atts); 
			}
			
			/// <summary>
			///  Opens a Acronym Html tag
			/// </summary>
			public static HtmlTextWriter Acronym(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("acronym", atts); 
			}
			
			/// <summary>
			///  Opens a Address Html tag
			/// </summary>
			public static HtmlTextWriter Address(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("address", atts); 
			}
			
			/// <summary>
			///  Opens a Area Html tag
			/// </summary>
			public static HtmlTextWriter Area(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("area", atts); 
			}
			
			/// <summary>
			///  Opens a B Html tag
			/// </summary>
			public static HtmlTextWriter B(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("b", atts); 
			}
			
			/// <summary>
			///  Opens a Base Html tag
			/// </summary>
			public static HtmlTextWriter Base(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("base", atts); 
			}
			
			/// <summary>
			///  Opens a Basefont Html tag
			/// </summary>
			public static HtmlTextWriter Basefont(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("basefont", atts); 
			}
			
			/// <summary>
			///  Opens a Bdo Html tag
			/// </summary>
			public static HtmlTextWriter Bdo(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("bdo", atts); 
			}
			
			/// <summary>
			///  Opens a Bgsound Html tag
			/// </summary>
			public static HtmlTextWriter Bgsound(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("bgsound", atts); 
			}
			
			/// <summary>
			///  Opens a Big Html tag
			/// </summary>
			public static HtmlTextWriter Big(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("big", atts); 
			}
			
			/// <summary>
			///  Opens a Blockquote Html tag
			/// </summary>
			public static HtmlTextWriter Blockquote(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("blockquote", atts); 
			}
			
			/// <summary>
			///  Opens a Body Html tag
			/// </summary>
			public static HtmlTextWriter Body(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("body", atts); 
			}
			
			/// <summary>
			///  Opens a Br Html tag
			/// </summary>
			public static HtmlTextWriter Br(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("br", atts); 
			}
			
			/// <summary>
			///  Opens a Button Html tag
			/// </summary>
			public static HtmlTextWriter Button(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("button", atts); 
			}
			
			/// <summary>
			///  Opens a Caption Html tag
			/// </summary>
			public static HtmlTextWriter Caption(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("caption", atts); 
			}
			
			/// <summary>
			///  Opens a Center Html tag
			/// </summary>
			public static HtmlTextWriter Center(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("center", atts); 
			}
			
			/// <summary>
			///  Opens a Cite Html tag
			/// </summary>
			public static HtmlTextWriter Cite(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("cite", atts); 
			}
			
			/// <summary>
			///  Opens a Code Html tag
			/// </summary>
			public static HtmlTextWriter Code(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("code", atts); 
			}
			
			/// <summary>
			///  Opens a Col Html tag
			/// </summary>
			public static HtmlTextWriter Col(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("col", atts); 
			}
			
			/// <summary>
			///  Opens a Colgroup Html tag
			/// </summary>
			public static HtmlTextWriter Colgroup(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("colgroup", atts); 
			}
			
			/// <summary>
			///  Opens a Dd Html tag
			/// </summary>
			public static HtmlTextWriter Dd(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("dd", atts); 
			}
			
			/// <summary>
			///  Opens a Del Html tag
			/// </summary>
			public static HtmlTextWriter Del(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("del", atts); 
			}
			
			/// <summary>
			///  Opens a Dfn Html tag
			/// </summary>
			public static HtmlTextWriter Dfn(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("dfn", atts); 
			}
			
			/// <summary>
			///  Opens a Dir Html tag
			/// </summary>
			public static HtmlTextWriter Dir(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("dir", atts); 
			}
			
			/// <summary>
			///  Opens a Div Html tag
			/// </summary>
			public static HtmlTextWriter Div(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("div", atts); 
			}
			
			/// <summary>
			///  Opens a Dl Html tag
			/// </summary>
			public static HtmlTextWriter Dl(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("dl", atts); 
			}
			
			/// <summary>
			///  Opens a Dt Html tag
			/// </summary>
			public static HtmlTextWriter Dt(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("dt", atts); 
			}
			
			/// <summary>
			///  Opens a Em Html tag
			/// </summary>
			public static HtmlTextWriter Em(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("em", atts); 
			}
			
			/// <summary>
			///  Opens a Embed Html tag
			/// </summary>
			public static HtmlTextWriter Embed(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("embed", atts); 
			}
			
			/// <summary>
			///  Opens a Fieldset Html tag
			/// </summary>
			public static HtmlTextWriter Fieldset(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("fieldset", atts); 
			}
			
			/// <summary>
			///  Opens a Font Html tag
			/// </summary>
			public static HtmlTextWriter Font(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("font", atts); 
			}
			
			/// <summary>
			///  Opens a Form Html tag
			/// </summary>
			public static HtmlTextWriter Form(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("form", atts); 
			}
			
			/// <summary>
			///  Opens a Frame Html tag
			/// </summary>
			public static HtmlTextWriter Frame(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("frame", atts); 
			}
			
			/// <summary>
			///  Opens a Frameset Html tag
			/// </summary>
			public static HtmlTextWriter Frameset(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("frameset", atts); 
			}
			
			/// <summary>
			///  Opens a H1 Html tag
			/// </summary>
			public static HtmlTextWriter H1(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("h1", atts); 
			}
			
			/// <summary>
			///  Opens a H2 Html tag
			/// </summary>
			public static HtmlTextWriter H2(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("h2", atts); 
			}
			
			/// <summary>
			///  Opens a H3 Html tag
			/// </summary>
			public static HtmlTextWriter H3(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("h3", atts); 
			}
			
			/// <summary>
			///  Opens a H4 Html tag
			/// </summary>
			public static HtmlTextWriter H4(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("h4", atts); 
			}
			
			/// <summary>
			///  Opens a H5 Html tag
			/// </summary>
			public static HtmlTextWriter H5(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("h5", atts); 
			}
			
			/// <summary>
			///  Opens a H6 Html tag
			/// </summary>
			public static HtmlTextWriter H6(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("h6", atts); 
			}
			
			/// <summary>
			///  Opens a Head Html tag
			/// </summary>
			public static HtmlTextWriter Head(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("head", atts); 
			}
			
			/// <summary>
			///  Opens a Hr Html tag
			/// </summary>
			public static HtmlTextWriter Hr(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("hr", atts); 
			}
			
			/// <summary>
			///  Opens a Html Html tag
			/// </summary>
			public static HtmlTextWriter Html(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("html", atts); 
			}
			
			/// <summary>
			///  Opens a I Html tag
			/// </summary>
			public static HtmlTextWriter I(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("i", atts); 
			}
			
			/// <summary>
			///  Opens a Iframe Html tag
			/// </summary>
			public static HtmlTextWriter Iframe(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("iframe", atts); 
			}
			
			/// <summary>
			///  Opens a Img Html tag
			/// </summary>
			public static HtmlTextWriter Img(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("img", atts); 
			}
			
			/// <summary>
			///  Opens a Input Html tag
			/// </summary>
			public static HtmlTextWriter Input(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("input", atts); 
			}
			
			/// <summary>
			///  Opens a Ins Html tag
			/// </summary>
			public static HtmlTextWriter Ins(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("ins", atts); 
			}
			
			/// <summary>
			///  Opens a Isindex Html tag
			/// </summary>
			public static HtmlTextWriter Isindex(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("isindex", atts); 
			}
			
			/// <summary>
			///  Opens a Kbd Html tag
			/// </summary>
			public static HtmlTextWriter Kbd(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("kbd", atts); 
			}
			
			/// <summary>
			///  Opens a Label Html tag
			/// </summary>
			public static HtmlTextWriter Label(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("label", atts); 
			}
			
			/// <summary>
			///  Opens a Legend Html tag
			/// </summary>
			public static HtmlTextWriter Legend(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("legend", atts); 
			}
			
			/// <summary>
			///  Opens a Li Html tag
			/// </summary>
			public static HtmlTextWriter Li(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("li", atts); 
			}
			
			/// <summary>
			///  Opens a Link Html tag
			/// </summary>
			public static HtmlTextWriter Link(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("link", atts); 
			}
			
			/// <summary>
			///  Opens a Map Html tag
			/// </summary>
			public static HtmlTextWriter Map(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("map", atts); 
			}
			
			/// <summary>
			///  Opens a Marquee Html tag
			/// </summary>
			public static HtmlTextWriter Marquee(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("marquee", atts); 
			}
			
			/// <summary>
			///  Opens a Menu Html tag
			/// </summary>
			public static HtmlTextWriter Menu(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("menu", atts); 
			}
			
			/// <summary>
			///  Opens a Meta Html tag
			/// </summary>
			public static HtmlTextWriter Meta(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("meta", atts); 
			}
			
			/// <summary>
			///  Opens a Nobr Html tag
			/// </summary>
			public static HtmlTextWriter Nobr(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("nobr", atts); 
			}
			
			/// <summary>
			///  Opens a Noframes Html tag
			/// </summary>
			public static HtmlTextWriter Noframes(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("noframes", atts); 
			}
			
			/// <summary>
			///  Opens a Noscript Html tag
			/// </summary>
			public static HtmlTextWriter Noscript(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("noscript", atts); 
			}
			
			/// <summary>
			///  Opens a Object Html tag
			/// </summary>
			public static HtmlTextWriter Object(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("object", atts); 
			}
			
			/// <summary>
			///  Opens a Ol Html tag
			/// </summary>
			public static HtmlTextWriter Ol(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("ol", atts); 
			}
			
			/// <summary>
			///  Opens a Option Html tag
			/// </summary>
			public static HtmlTextWriter Option(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("option", atts); 
			}
			
			/// <summary>
			///  Opens a P Html tag
			/// </summary>
			public static HtmlTextWriter P(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("p", atts); 
			}
			
			/// <summary>
			///  Opens a Param Html tag
			/// </summary>
			public static HtmlTextWriter Param(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("param", atts); 
			}
			
			/// <summary>
			///  Opens a Pre Html tag
			/// </summary>
			public static HtmlTextWriter Pre(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("pre", atts); 
			}
			
			/// <summary>
			///  Opens a Q Html tag
			/// </summary>
			public static HtmlTextWriter Q(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("q", atts); 
			}
			
			/// <summary>
			///  Opens a Rt Html tag
			/// </summary>
			public static HtmlTextWriter Rt(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("rt", atts); 
			}
			
			/// <summary>
			///  Opens a Ruby Html tag
			/// </summary>
			public static HtmlTextWriter Ruby(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("ruby", atts); 
			}
			
			/// <summary>
			///  Opens a S Html tag
			/// </summary>
			public static HtmlTextWriter S(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("s", atts); 
			}
			
			/// <summary>
			///  Opens a Samp Html tag
			/// </summary>
			public static HtmlTextWriter Samp(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("samp", atts); 
			}
			
			/// <summary>
			///  Opens a Script Html tag
			/// </summary>
			public static HtmlTextWriter Script(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("script", atts); 
			}
			
			/// <summary>
			///  Opens a Select Html tag
			/// </summary>
			public static HtmlTextWriter Select(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("select", atts); 
			}
			
			/// <summary>
			///  Opens a Small Html tag
			/// </summary>
			public static HtmlTextWriter Small(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("small", atts); 
			}
			
			/// <summary>
			///  Opens a Span Html tag
			/// </summary>
			public static HtmlTextWriter Span(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("span", atts); 
			}
			
			/// <summary>
			///  Opens a Strike Html tag
			/// </summary>
			public static HtmlTextWriter Strike(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("strike", atts); 
			}
			
			/// <summary>
			///  Opens a Strong Html tag
			/// </summary>
			public static HtmlTextWriter Strong(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("strong", atts); 
			}
			
			/// <summary>
			///  Opens a Style Html tag
			/// </summary>
			public static HtmlTextWriter Style(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("style", atts); 
			}
			
			/// <summary>
			///  Opens a Sub Html tag
			/// </summary>
			public static HtmlTextWriter Sub(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("sub", atts); 
			}
			
			/// <summary>
			///  Opens a Sup Html tag
			/// </summary>
			public static HtmlTextWriter Sup(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("sup", atts); 
			}
			
			/// <summary>
			///  Opens a Table Html tag
			/// </summary>
			public static HtmlTextWriter Table(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("table", atts); 
			}
			
			/// <summary>
			///  Opens a Tbody Html tag
			/// </summary>
			public static HtmlTextWriter Tbody(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("tbody", atts); 
			}
			
			/// <summary>
			///  Opens a Td Html tag
			/// </summary>
			public static HtmlTextWriter Td(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("td", atts); 
			}
			
			/// <summary>
			///  Opens a Textarea Html tag
			/// </summary>
			public static HtmlTextWriter Textarea(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("textarea", atts); 
			}
			
			/// <summary>
			///  Opens a Tfoot Html tag
			/// </summary>
			public static HtmlTextWriter Tfoot(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("tfoot", atts); 
			}
			
			/// <summary>
			///  Opens a Th Html tag
			/// </summary>
			public static HtmlTextWriter Th(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("th", atts); 
			}
			
			/// <summary>
			///  Opens a Thead Html tag
			/// </summary>
			public static HtmlTextWriter Thead(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("thead", atts); 
			}
			
			/// <summary>
			///  Opens a Title Html tag
			/// </summary>
			public static HtmlTextWriter Title(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("title", atts); 
			}
			
			/// <summary>
			///  Opens a Tr Html tag
			/// </summary>
			public static HtmlTextWriter Tr(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("tr", atts); 
			}
			
			/// <summary>
			///  Opens a Tt Html tag
			/// </summary>
			public static HtmlTextWriter Tt(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("tt", atts); 
			}
			
			/// <summary>
			///  Opens a U Html tag
			/// </summary>
			public static HtmlTextWriter U(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("u", atts); 
			}
			
			/// <summary>
			///  Opens a Ul Html tag
			/// </summary>
			public static HtmlTextWriter Ul(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("ul", atts); 
			}
			
			/// <summary>
			///  Opens a Var Html tag
			/// </summary>
			public static HtmlTextWriter Var(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("var", atts); 
			}
			
			/// <summary>
			///  Opens a Wbr Html tag
			/// </summary>
			public static HtmlTextWriter Wbr(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("wbr", atts); 
			}
			
			/// <summary>
			///  Opens a Xml Html tag
			/// </summary>
			public static HtmlTextWriter Xml(this HtmlTextWriter writer, object atts = null)
			{
				return writer.PushTag("xml", atts); 
			}
	
		#endregion

		/// <summary>
		///  Closes the most recently opened tag
		/// </summary>
		public static HtmlTextWriter EndTag(this HtmlTextWriter writer)
        {
            WritePreceeding(writer);
            writer.RenderEndTag();
            return writer;
        }

		/// <summary>
		///  Writes  content to the current tag
		/// </summary>
        public static HtmlTextWriter WriteContent(this HtmlTextWriter writer, string content)
        {
            WritePreceeding(writer);
            writer.Write(content);
            return writer;
        }

		/// <summary>
		///  Writes the specified objects properties as tag attributes
		/// </summary>
        public static HtmlTextWriter Attributes(this HtmlTextWriter writer, object atts)
        {
            tags.Peek().AttributeContainer = atts;
            
            return writer;
        }

		/// <summary>
		///  Writes to the underlying writer any current content
		/// </summary>
        private static void WritePreceeding(HtmlTextWriter writer)
        {
            if (tags.Count > 0)
            {
                var popped = tags.Pop();

                if (popped.AttributeContainer != null)
                {
                    var props = popped.AttributeContainer.GetType().GetProperties();

                    foreach (var p in props)
                    {
                        var val = p.GetValue(popped.AttributeContainer, null).ToString();
                        writer.AddAttribute(p.Name, val);
                    }
                }

                writer.RenderBeginTag(popped.TagName);
            }
        }

		/// <summary>
		///  Helper class to store a tag and it's attributes on the stack
		/// </summary>
		private class Tag
        {
            public string TagName { get; private set; }
            public object AttributeContainer { get; set; }

            public Tag(string tagName, object container = null)
            {
                TagName = tagName;
                AttributeContainer = container;
            }
        }
	}
}
